#ifndef __GLF_TASK_TASKHANDLERPOLICY_IMPL_H_INCLUDED__
#define __GLF_TASK_TASKHANDLERPOLICY_IMPL_H_INCLUDED__

#include <glf/core/inlines.h>
#include <glf/core/timer.h>
#include <glf/task/task.h>

namespace glf {

template<typename Tag>
bool TaskHandlerConsumeSingle<Tag>::Consume()
{
	Task* task = TaskManager::GetInstance<Tag>().Pop();

	if(task)
	{
		// We need to verify if the task is managed prior of calling Run()
		// Once it is called, CpuTask may be invalid if it is not managed.
		// Calling CpuTask->isManaged() after CpuTask->run() could result
		// in a bad access as stack allocated task will auto-delete itself
		// and the memory space for the managed boolean could be overitten
		// with true, and so this code will try to delete a stack allocated
		// task.
		bool isManaged = task->IsManaged();
		task->MyRun();

		if(isManaged)
		{
			delete task;
		}

		// Since we poped a valid task, we assume there are other tasks left,
		// So continue running if the task manager for this tag is still
		// active.
		return true;
	}

	// No more tasks to proceed
	return false;
}

template<typename Tag>
bool TaskHandlerConsumeDrain<Tag>::Consume()
{
	// Drain all tasks
	while(TaskHandlerConsumeSingle<Tag>::Consume())
	{
	}

	// No more tasks to proceed
	return false;
}

template<typename Tag>
TaskHandlerConsumeTimeSlice<Tag>::TaskHandlerConsumeTimeSlice()
	: m_TimeSlice(DEFAULT_TIME_SLICE)
{
}

template<typename Tag>
TaskHandlerConsumeTimeSlice<Tag>::TaskHandlerConsumeTimeSlice(int64 timeSlice)
	: m_TimeSlice(timeSlice)
{
}

template<typename Tag>
void TaskHandlerConsumeTimeSlice<Tag>::SetTimeSlice(int64 timeSlice)
{
	m_TimeSlice = timeSlice;
}

template<typename Tag>
bool TaskHandlerConsumeTimeSlice<Tag>::Consume()
{
	int64 endTime = GetMicroseconds() + m_TimeSlice;

	bool hasPendingTasks = false;
	do
	{
		hasPendingTasks = false;
		hasPendingTasks |= TaskHandlerConsumeSingle<Tag>::Consume();
	}
	while(hasPendingTasks && endTime > GetMicroseconds());

	return hasPendingTasks;
}

} // end namespace glf

#endif // __GLF_TASK_TASKHANDLERPOLICY_IMPL_H_INCLUDED__
